"""
Case Type   : 资源池化系统视图
Case Name   : 配置较小max_process_memory，运行适量业务，查看相关系统视图中DMSDrcContext统计信息
Create At   : 2025/2
Owner       : haomeng
Description :
    1、查看内存保护开关，查看线程池开关
    2、设置max_process_memory为系统内存约20%左右
    3、运行适当tpcc业务
    4、主备节点查看系统表中DMSDrcContext字段是否存在以及值是否正常
    5、主备节点分别查看系统表gs_shared_memory_detail中DMSDrcContext字段是否存在
    6、主备节点分别查看系统表gs_thread_memory_context中DMSMemContext字段是否存在
    7、主备节点分别查看关联函数dbe_perf.track_memory_context_detail信息
    8、恢复环境初始状态
Expect      :
    1、前者默认为on打开，后者默认为off
    2、设置成功
    3、业务运行成功
    4、无相关信息
    5、存在DMSDrcContext相关字段及信息
    6、存在DMSMemContext相关字段及信息
    7、无相关信息
    8、恢复环境成功
History     :
"""

import os
import time
import unittest

from testcase.utils.Common import Common
from testcase.utils.CommonSH import CommonSH
from testcase.utils.Constant import Constant
from testcase.utils.Logger import Logger
from yat.test import Node
from yat.test import macro


class ShareStorageSystemView(unittest.TestCase):

    def setUp(self):
        self.log = Logger()
        self.log.info(f'----{os.path.basename(__file__)} start----')
        self.user_node = [CommonSH('PrimaryDbUser'), CommonSH('Standby1DbUser'), CommonSH('Standby2DbUser')]
        self.pri_user = [Node(node='PrimaryDbUser'), Node('PrimaryRoot')]
        self.com = Common('PrimaryDbUser')
        self.constant = Constant()

        self.param1 = 'enable_memory_limit'
        self.param2 = 'enable_thread_pool'
        self.param3 = 'max_process_memory'

        self.sys_view1 = 'pg_total_memory_detail'
        self.sys_view2 = 'gs_total_memory_detail'
        self.sys_view3 = 'gs_shared_memory_detail'
        self.sys_view4 = 'pg_shared_memory_detail()'
        self.sys_view5 = 'gs_thread_memory_context'
        self.sys_view6 = 'gs_session_memory_detail'
        self.sys_view7 = 'gs_get_thread_memctx_detail'
        self.sys_view8 = 'dbe_perf.track_memory_context'
        self.sys_view9 = 'dbe_perf.track_memory_context_detail()'

    def test_ss_system_view(self):
        text = '-----step1:查看mes相关配置默认值  expect:查看成功-----'
        self.log.info(text)

        self.param_list = [self.param1, self.param2, self.param3]
        value_list = ['on', 'off']

        self.default_value = []
        for param in self.param_list:
            value = self.user_node[0].execut_db_sql(f'show {param}')
            tmp = value.splitlines()[-2].strip() if value.splitlines()[-2].strip() else "''"
            self.default_value.append(tmp)
        self.log.info(self.default_value)
        self.assertEqual(self.default_value[0:2], value_list[0:2], '参数值与预期不一致')

        text = '-----step2:设置max_process_memory为系统内存约20%左右  expect:设置成功-----'
        self.log.info(text)

        self.log.info('-----查看当前系统内存大小-----')
        memory = f"free -g | awk 'NR==2' | awk -F ' ' '{{{{print$2}}}}'"
        self.log.info(memory)
        memory_size = self.pri_user[0].sh(memory).result()
        self.log.info(memory_size)

        set_value = round(int(memory_size * 0.2))
        self.log.info(set_value)

        set_param = self.user_node[0].execute_gsguc('set',
                                                    self.constant.GSGUC_SUCCESS_MSG,
                                                    f"{self.param3} = {set_value}GB")
        self.log.info(set_param)
        self.assertTrue(set_param, '参数设置失败')

        self.log.info('---重启集群使参数生效---')
        restart = self.user_node[0].restart_db_cluster(False)
        self.log.info(restart)
        self.assertTrue(restart)

        self.log.info('---查看参数值修改是否成功---')
        value = self.user_node[0].execut_db_sql(f'show {self.param3};')
        res = value.splitlines()[-2].strip() if value.splitlines()[-2].strip() else "''"
        self.assertEqual(int(res.split('GB')[0]), set_value, '参数未修改成功')

        text = '-----step3:运行适当tpcc业务  expect:业务运行成功-----'
        self.log.info(text)

        tpcc_cmd = f'./runBenchmark.sh {macro.PROPS_FILENAME}'
        self.log.info(tpcc_cmd)

        tpcc_execute = self.com.startTPCC(self.pri_user[1], f'{macro.TPCC_PATH}', tpcc_cmd)
        self.log.info(tpcc_execute)
        self.assertIn('Session End', tpcc_execute, 'TPCC业务运行失败')

        text = '-----step4:主备节点查看系统视图pg_total_memory_detail中DMSDrcContext字段' \
               '是否存在  expect:无相关信息-----'
        self.log.info(text)

        sql1 = f"select * from {self.sys_view1} where memorytype='DMSDrcContext';"
        self.log.info(sql1)
        sql2 = f"select * from {self.sys_view2} where memorytype='DMSDrcContext';"
        self.log.info(sql2)

        for node in self.user_node:
            res1 = node.execut_db_sql(sql1)
            self.log.info(res1)
            self.assertIn('(0 rows)', res1, '存在异常信息')

        for node in self.user_node:
            res2 = node.execut_db_sql(sql2)
            self.log.info(res2)
            self.assertIn('(0 rows)', res2, '存在异常信息')

        text = '-----step5:主备节点查看系统表gs_shared_memory_detail中DMSDrcContext字段' \
               '是否存在  expect:存在DMSDrcContext相关字段及信息-----'
        self.log.info(text)

        sql3 = f"select * from {self.sys_view3} where contextname='DMSDrcContext';"
        self.log.info(sql3)
        sql4 = f"select * from {self.sys_view4} where contextname='DMSDrcContext';"
        self.log.info(sql4)

        for node in self.user_node:
            res3 = node.execut_db_sql(sql3)
            self.log.info(res3)
            self.assertIn('DMSDrcContext', res3.splitlines()[-2], '存在异常信息')

        for node in self.user_node:
            res4 = node.execut_db_sql(sql4)
            self.log.info(res4)
            self.assertIn('DMSDrcContext', res4.splitlines()[-2], '存在异常信息')

        text = '-----step6:主备节点查看系统表gs_thread_memory_context中DMSMemContext字段' \
               '是否存在  expect:存在DMSMemContext相关字段及信息-----'
        self.log.info(text)

        sql5 = f"select * from {self.sys_view5} where contextname = 'DMSMemContext';"
        self.log.info(sql5)
        sql6 = f"select * from {self.sys_view6} where contextname = 'DMSMemContext';"
        self.log.info(sql6)

        for node in self.user_node:
            res5 = node.execut_db_sql(sql5)
            self.log.info(res5)
            self.assertIn('DMSMemContext', res5, '存在异常信息')

            res6 = node.execut_db_sql(sql6)
            self.log.info(res6)
            self.assertIn('DMSMemContext', res6.splitlines()[-2], '存在异常信息')

            rows, _ = self.com.parse_sql_query_res(res6)
            tid1 = rows[0][0].split('.')[-1]
            sql7 = f"select * from {self.sys_view7}({tid1},'DMSMemContext');"
            self.log.info(sql7)
            res7 = node.execut_db_sql(sql7)
            self.log.info(res7)
            self.assertIn('ss_dms_callback.cpp', res7, '存在异常信息')

        text = '-----step7:主备节点查看系统表dbe_perf.track_memory_context_detail中' \
               'DMSDrcContext字段是否存在  expect:无相关信息-----'
        self.log.info(text)

        sql8 = f"select * from {self.sys_view8}('DMSDrcContext');"
        self.log.info(sql8)

        for node in self.user_node:
            res8 = node.execut_db_sql(sql8)
            self.log.info(res8)
            self.assertEqual('t', res8.splitlines()[-2].strip(), '存在异常信息')

            res9 = node.execut_db_sql(f"select * from {self.sys_view9};", dbname='postgres')
            self.log.info(res9)
            self.assertIn('(0 rows)', res9, '存在异常信息')

    def tearDown(self):
        text = '-----step8:恢复初始环境  expect:恢复成功-----'
        self.log.info(text)

        reset_param = self.user_node[0].execute_gsguc('set',
                                                      self.constant.GSGUC_SUCCESS_MSG,
                                                      f'{self.param3} = {self.default_value[2]}')
        self.log.info(reset_param)

        restart = self.user_node[0].restart_db_cluster(False)
        self.log.info(restart)

        status = self.user_node[0].exec_cm_ctl('query', '-Cv')
        self.log.info(status)

        for param in self.param_list:
            reset_value = self.user_node[0].execut_db_sql(f'show {param};')
            self.log.info(reset_value)
            res = reset_value.splitlines()[-2].strip() if reset_value.splitlines()[-2].strip() else "''"
            self.assertEqual(res, self.default_value[self.param_list.index(param)], '参数恢复失败')
        self.assertIn('Primary Normal', status.splitlines()[-1].split('|')[0],
                      '恢复集群初始状态失败')
        self.log.info(f'----{os.path.basename(__file__)} end----')
